<?php

declare(strict_types=1);

namespace app\sys\controller\api;

use app\sys\service\fileService;
use think\admin\Controller;
use think\admin\Exception;
use think\admin\model\SysFile;
use think\admin\model\SysUser;
use think\admin\service\AdminService;
use think\admin\Storage;
use think\admin\storage\LocalStorage;
use think\exception\HttpResponseException;
use think\file\UploadedFile;

/**
 * 文件接口
 * Class File
 * @package app\sys\controller
 */
class File extends Controller
{
    /**
     * 用户更新头像（转base64）
     * @login true
     * @return void
     * @throws Exception
     */
    public function updateAvatar()
    {
        // 开始处理文件上传
        $file = $this->getFile();
        $extension = strtolower($file->getOriginalExtension());
        $saveFileName = input('key') ?: Storage::name($file->getPathname(), $extension, '', 'md5_file');
        $size = $file->getSize();
        [$state,$msg] = fileService::performFileSecurityCheck($saveFileName, $extension);
        if(!$state) $this->error($msg);
        try {
            $safeMode = fileService::getSafe();
            $local = LocalStorage::instance();
            $distName = $local->path($saveFileName, $safeMode);
            if (PHP_SAPI === 'cli') {
                is_dir(dirname($distName)) || mkdir(dirname($distName), 0777, true);
                rename($file->getPathname(), $distName);
            } else {
                $file->move(dirname($distName), basename($distName));
            }
            $info = $local->info($saveFileName, $safeMode, $file->getOriginalName());
            if (in_array($extension, ['jpg', 'gif', 'png', 'bmp', 'jpeg', 'wbmp'])) {
                if (fileService::imgNotSafe($distName) && $local->del($saveFileName)) {
                    $this->error('图片未通过安全检查！');
                }
                [$width, $height] = getimagesize($distName);
                if (($width < 1 || $height < 1) && $local->del($saveFileName)) {
                    $this->error('读取图片的尺寸失败！');
                }

            }
            $avatar = str_replace("\r\n", "", base64EncodeImage($distName));
            [$uuid, $unid, $unexts] = fileService::initUnid();
            if ($avatar) {
                SysUser::mk()->where(['id' => $uuid])->update(['avatar' => $avatar]);
                @unlink($distName);
                $this->success('上传成功！', $avatar);
            } else {
                $this->error('上传处理失败，请稍候再试！');
            }
        } catch (HttpResponseException $exception) {
            throw $exception;
        } catch (\Exception $exception) {
            trace_file($exception);
            $this->error($exception->getMessage());
        }
    }


    /**
     * 文件上传入口
     * @login true
     * @throws Exception
     */
    public function fileUpload()
    {
        // 开始处理文件上传
        $file = $this->getFile();
        $extension = strtolower($file->getOriginalExtension());
        $saveFileName = input('key') ?: Storage::name($file->getPathname(), $extension, '', 'md5_file');
        $size = $file->getSize();
        [$state,$msg] = fileService::performFileSecurityCheck($saveFileName, $extension);
        if(!$state) $this->error($msg);
        try {
            $type = fileService::getType();
            $safeMode = fileService::getSafe();
            if ($type === 'local') {
                $local = LocalStorage::instance();
                $distName = $local->path($saveFileName, $safeMode);
                //$size = filesize($distName);
                if (PHP_SAPI === 'cli') {
                    is_dir(dirname($distName)) || mkdir(dirname($distName), 0777, true);
                    rename($file->getPathname(), $distName);
                } else {
                    $file->move(dirname($distName), basename($distName));
                }
                $info = $local->info($saveFileName, $safeMode, $file->getOriginalName());
                if (in_array($extension, ['jpg', 'gif', 'png', 'bmp', 'jpeg', 'wbmp'])) {
                    if (fileService::imgNotSafe($distName) && $local->del($saveFileName)) {
                        $this->error('图片未通过安全检查！');
                    }
                    [$width, $height] = getimagesize($distName);
                    if (($width < 1 || $height < 1) && $local->del($saveFileName)) {
                        $this->error('读取图片的尺寸失败！');
                    }
                }
            } else {
                $bina = file_get_contents($file->getPathname());
                $info = Storage::instance($type)->set($saveFileName, $bina, $safeMode, $file->getOriginalName());
            }
            if (isset($info['url'])) {
                $fileData = [
                    'merchant_id' => AdminService::getMerchantId(),
                    'engine' => $type,
                    'bucket' => fileService::getBucket($type),
                    'name' => $file->getOriginalName(),
                    'suffix' => $extension,
                    'size_kb' => $size,
                    'size_info' => format_bytes($size),
                    'obj_name' => $info['key'],
                    'storage_path' => $info['url'],
                    'created_by' => AdminService::getUserId()
                ];
                $fileId = SysFile::mk()->insertGetId($fileData);
                $this->success('文件上传成功！', ['url' => $safeMode ? $saveFileName : $info['url'], 'status' => 'done', 'id' => $fileId, 'name' => $file->getOriginalName(), 'ext' => $extension]);
            } else {
                $this->error('文件处理失败，请稍候再试！', ['status' => 'error']);
            }
        } catch (HttpResponseException $exception) {
            throw $exception;
        } catch (\Exception $exception) {
            trace_file($exception);
            $this->error($exception->getMessage());
        }
    }

    /**
     * 获取文件对象
     * @return UploadedFile|void
     */
    private function getFile(): UploadedFile
    {
        try {
            $file = $this->request->file('file');
            if ($file instanceof UploadedFile) {
                return $file;
            } else {
                $this->error('未获取到上传的文件对象！');
            }
        } catch (HttpResponseException $exception) {
            throw $exception;
        } catch (\Exception $exception) {
            trace_file($exception);
            $this->error(lang($exception->getMessage()));
        }
    }
}